package xyz.labmem.service

import cn.hutool.core.lang.Console
import cn.hutool.core.util.StrUtil
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONArray
import com.alibaba.fastjson.JSONObject
import javafx.application.Platform
import javafx.concurrent.Task
import org.openqa.selenium.ElementNotInteractableException
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.SessionNotCreatedException
import org.openqa.selenium.WebElement
import xyz.labmem.core.base.BaseController
import xyz.labmem.core.exception.LabRunException
import xyz.labmem.config.BrowserReptileConfig
import xyz.labmem.config.BrowserReptileTask
import xyz.labmem.controller.BrowserReptileController
import java.io.FileWriter
import java.nio.charset.StandardCharsets
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardOpenOption
import java.util.*
import kotlin.collections.ArrayList
import kotlin.jvm.Throws


/**
 * 爬虫执行类
 * @Author lty
 * @Date 2021/9/30 10:02
 */
class ReptileOperating(controller: BaseController) {

    private val confPath: Path = Paths.get(BrowserReptileConfig.configPath, "tasks.labconf")
    private val base = controller as BrowserReptileController

    enum class Status {
        SUCCESS,
        FAILED,
        ERROR,
        FINALLY,
    }

    /**
     * 测试驱动是否正常
     */
    fun test() {
        val loading = base.loading.apply {
            getMasker().text = "正在测试驱动.."
            show()
            base.server.showLog("开始进行测试")
        }
        //编写测试任务
        val testTask = BrowserReptileTask().apply {
            name = "测试"
            url = "https://baidu.com"
            script="""
                main{
//                    hook().byId('s_top_wrap')
//                    var wd=selectEle().byXpath('//*[@id="kw"]')
//                    wd.input(dd)
//                    selectEle().byId('form').submit()
//                    sleep(10000)
                      var list=['呵呵','呼呼']
                      list.each
                        console(it)
                        sleep(3000)
                      #each
                }
            """.trimIndent()
        }
        Thread(base.engine.run(testTask).apply {
            setOnSucceeded {
                loading.hide()
                base.server.showLog("测试结束。")
            }
            setOnFailed {
                base.getTray().winMsgError(null, "测试失败!")
                loading.hide()
                base.server.showLog("测试失败")
            }
            messageProperty().addListener { msg, _, _ ->
                if (msg.value.equals(Status.SUCCESS.name)) {
                    base.server.showLog("测试成功！")
                    base.getTray().winMsgInfo(null, "测试成功!")
                }
                if (msg.value.equals(Status.ERROR.name)) {
                    base.server.showLog("测试失败！")
                    loading.hide()
                }
            }
        }).start()

    }

    //保存任务
    @Throws(LabRunException::class)
    fun saveTask(task: BrowserReptileTask) {
        saveTask(task, -1)
    }

    //保存任务
    @Throws(LabRunException::class)
    fun saveTask(task: BrowserReptileTask, index: Int) {
        var tasks = getTask()
        if (tasks != null) {
            if (index == -1) {
                tasks.add(task)
            } else {
                tasks[index] = task
            }
        } else {
            tasks = ArrayList<BrowserReptileTask>()
            tasks.add(task)
        }
        saveTask(tasks)
    }


    //保存任务
    @Throws(LabRunException::class)
    fun saveTask(tasks: MutableList<BrowserReptileTask>) {
        val taskString: String = JSON.toJSONString(tasks)
        Console.log("写入配置文件：$taskString")
        try {
            val conf = confPath.toFile()
            if (!conf.exists()) {
                if (conf.parentFile.mkdirs()) {
                    Files.createFile(confPath)
                }
                try {
                    Files.write(
                        confPath,
                        taskString.toByteArray(StandardCharsets.UTF_8),
                        StandardOpenOption.CREATE
                    )
                } catch (ex: Exception) {
                    throw LabRunException("写入配置文件失败", ex)
                }
            } else {
                try {
                    FileWriter(conf).apply {
                        write(taskString)
                        flush()
                        close()
                    }
                } catch (ex: Exception) {
                    throw LabRunException("修改配置文件失败", ex)
                }
            }
        } catch (e: Exception) {
            throw LabRunException("创建配置文件失败", e)
        }
    }

//    fun saveTask() {
//        val task = object : Task<Void>() {
//            override fun call(): Void? {
//                updateMessage("正在保存。。")
//                val task = BrowserReptileTask().apply {
//                    name = "任务1"
//                    url = "https://bilibili.com"
//                    taskType = BrowserReptileTask.TaskType.ONLY_OPERATE
//                    steps = LinkedList<BrowserReptileTask.Step>().apply {
//                        add(
//                            BrowserReptileTask.Step().apply {
//                                type = BrowserReptileTask.Step.Type.WAIT
//                                className = "first-screen b-wrap"
//                            }
//                        )
//                        add(
//                            BrowserReptileTask.Step().apply {
//                                type = BrowserReptileTask.Step.Type.ELEMENT
//                                index = 0
//                                className = "rcmd-box-wrap"
//                            }
//                        )
//                        add(
//                            BrowserReptileTask.Step().apply {
//                                type = BrowserReptileTask.Step.Type.ELEMENT
//                                index = 0
//                                className = "video-card-reco"
//                            }
//                        )
//                        add(
//                            BrowserReptileTask.Step().apply {
//                                type = BrowserReptileTask.Step.Type.CLICK
//                                index = 0
//                                tag = "a"
//                            }
//                        )
//                    }
//                }
//                val taskString: String
//                updateProgress(0.2, 1.0)
//                val tasks = getTask()
//                updateProgress(0.5, 1.0)
//
//                if (tasks != null) {
//                    tasks.add(task)
//                    taskString = JSON.toJSONString(tasks)
//                } else {
//                    JSONArray().apply {
//                        add(task)
//                        taskString = toJSONString()
//                    }
//                }
//                try {
//                    val conf = confPath.toFile()
//                    if (!conf.exists()) {
//                        if (conf.parentFile.mkdirs()) {
//                            Files.createFile(confPath)
//                        }
//                    }
//                    updateProgress(0.8, 1.0)
//                    try {
//                        Files.write(
//                            confPath,
//                            taskString.toByteArray(StandardCharsets.UTF_8),
//                            StandardOpenOption.CREATE
//                        )
//                        Platform.runLater { base.alertUtil.noticeSuccess("保存成功！").show() }
//                    } catch (ex: Exception) {
//                        ex.printStackTrace()
//                        Platform.runLater { base.alertUtil.noticeError("写入配置文件失败！").show() }
//                    }
//                } catch (e: Exception) {
//                    e.printStackTrace()
//                    Platform.runLater { base.alertUtil.noticeError("创建配置文件失败！").show() }
//                } finally {
//                    done()
//                }
//                return null
//            }
//        }
//        base.loading.simpleTask(task)
//    }


    //获取任务
    fun getTask(): MutableList<BrowserReptileTask>? {
        if (Files.exists(confPath)) {
            try {
                val bytes = Files.readAllBytes(confPath)
                val jsonString = String(bytes)
                return JSON.parseArray(jsonString, BrowserReptileTask::class.java)
            } catch (e: Exception) {
                Console.error("读取文件失败{}", confPath.toAbsolutePath(), e)
            }
        }
        return null
    }

//    //执行任务
//    fun runTask(task: BrowserReptileTask, outData: JSONArray): Task<DriverOperating> {
//        return object : Task<DriverOperating>() {
//            override fun call(): DriverOperating? {
//                Platform.runLater { updateProgress(0.0, 1.0) }
//                var frequency = 1   //执行次数
//                var operating: DriverOperating? = null
//                try {
//                    //创建浏览器
//                    operating = DriverOperating()
//                    updateValue(operating)
//                    //获取任务配置
//                    task.config?.let {
//                        if (it.frequency > 1)
//                            frequency = it.frequency
//                        if (it.outTime != null)
//                            operating.outTime = it.outTime!!
//                        if (it.threadSleep != null)
//                            operating.outTime = it.threadSleep!!
//                        if (it.uploadOutTime != null)
//                            operating.outTime = it.uploadOutTime!!
//                    }
//                    Platform.runLater { updateProgress(0.15, 1.0) }
//                    operating.apply {
//                        var progress = 0.0
//                        //计算步骤进度
//                        if (task.steps != null) {
//                            progress = 0.85.div(task.steps!!.size * frequency)
//                        }
//
//                        //打开页面
//                        driver.get(task.url)
//                        while (frequency > 0) {
//                            val collect = JSONObject()
//                            //选中的元素
//                            val elements = LinkedList<WebElement>()
//                            var elementIndex = 0  //0表示只有一个，-1表示全部,-2表示没有指定元素
//                            //执行步骤
//                            task.steps?.forEach {
//                                when (it.type) {
//                                    BrowserReptileTask.Step.Type.CLICK -> {
//                                        useSelectElement(elements, it, operating, elementIndex).click()
//                                    }
//                                    BrowserReptileTask.Step.Type.ELEMENT -> {
//                                        elementIndex = selectElementType(elements, it, operating, elementIndex)
//                                    }
//                                    BrowserReptileTask.Step.Type.WAIT -> {
//                                        if (StrUtil.isNotBlank(it.xpath))
//                                            loadingFindFlagByXpath(it.xpath!!)
//                                        else if (StrUtil.isNotBlank(it.id))
//                                            loadingFindFlagById(it.id!!)
//                                        else if (StrUtil.isNotBlank(it.className))
//                                            loadingFindFlagByClass(it.className!!)
//                                    }
//                                    BrowserReptileTask.Step.Type.BACK_PATH -> {
//                                        driver.navigate().back()
//                                    }
//                                    BrowserReptileTask.Step.Type.TO -> {
//                                        driver.navigate().to(it.value)
//                                    }
//                                    BrowserReptileTask.Step.Type.REFRESH -> {
//                                        driver.navigate().refresh()
//                                    }
//                                    BrowserReptileTask.Step.Type.INPUT -> {
//                                        var value = it.value
//                                        if (StrUtil.isBlank(value) && StrUtil.isNotBlank(it.fieName)) {
//                                            value = collect[it.fieName].toString()
//                                        }
//                                        useSelectElement(elements, it, operating, elementIndex).sendKeys(value)
//                                    }
//                                    BrowserReptileTask.Step.Type.OUTPUT -> {
//                                        val e = useSelectElement(elements, it, operating, elementIndex)
//                                        if (it.getBy == BrowserReptileTask.Step.GetBy.TEXT)
//                                            collect[it.fieName] = getElementText(e, it.fieName)
//                                        else if (it.getBy == BrowserReptileTask.Step.GetBy.ATTRIBUTE)
//                                            collect[it.fieName] =
//                                                getElementAttribute(e, it.value!!, it.fieName)
//                                        base.server.showLog("【${task.name}】任务取值${it.fieName}=${collect[it.fieName]}")
//                                    }
//                                    BrowserReptileTask.Step.Type.SLEEP -> {
//                                        it.sleep?.let { s -> Thread.sleep(s) }
//                                    }
//                                    BrowserReptileTask.Step.Type.CLEAN_ELEMENT -> {
//                                        elementIndex = 0
//                                        elements.clear()
//                                    }
//                                    BrowserReptileTask.Step.Type.SAVE_PHOTO -> {
//                                        savePhoto(
//                                            useSelectElement(elements, it, operating, elementIndex),
//                                            it.value!! + "/${it.fieName}.png"
//                                        )
//                                    }
//                                    BrowserReptileTask.Step.Type.JAVASCRIPT -> {
//                                        try {
//                                            (driver as JavascriptExecutor).executeScript(it.value)
//                                        } catch (e: Exception) {
//                                            throw LabRunException(e)
//                                        }
//                                    }
//                                    BrowserReptileTask.Step.Type.SUBMIT -> {
//                                        useSelectElement(elements, it, operating, elementIndex).submit()
//                                    }
//                                    else -> {
//                                    }
//                                }
//                                Platform.runLater { updateProgress(getProgress() + progress, 1.0) }
//                            }
//                            outData.add(collect)
//                            frequency--
//                            Thread.sleep(300)
//                        }
//                    }
//                    Platform.runLater { updateProgress(1.0, 1.0) }
//                    succeeded()
//                    updateMessage(Status.SUCCESS.name)
//                } catch (e: LabRunException) {
//                    base.getTray().winMsgError("任务执行错误！", e.message ?: "【${task.name}】任务执行失败！详见日志")
//                    updateMessage(Status.ERROR.name)
//                    base.server.showLog("【${task.name}】任务执行有误：${e.message}")
//                } catch (e: SessionNotCreatedException) {
//                    e.printStackTrace()
//                    base.getTray().winMsgError("Chrome创建失败！", "请检查驱动和Chrome版本")
//                    updateMessage(Status.ERROR.name)
//                    base.server.showLog("【${task.name}】Chrome创建失败：${e.message}")
//                } catch (e: ElementNotInteractableException) {
//                    base.getTray().winMsgError("元素未找到", "若页面加载慢请添加钩子确保页面正确！")
//                    updateMessage(Status.ERROR.name)
//                    base.server.showLog(
//                        "【${task.name}】任务执行元素未找到,若页面加载慢请添加钩子确保页面正确再进行！error:" +
//                                e.message!!.substring(
//                                    e.message!!.lastIndexOf("Element:"),
//                                    e.message!!.lastIndexOf("Session ID:")
//                                )
//                    )
//                } catch (e: Exception) {
//                    e.printStackTrace()
//                    base.getTray().winMsgError("任务执行错误！", e.message ?: "启动失败！详见日志")
//                    updateMessage(Status.ERROR.name)
//                    base.server.showLog("【${task.name}】任务执行报错：${e.message}")
//                } finally {
//                    operating?.driverEnd()
//                }
//                return operating
//            }
//        }
//    }

//    @Throws(LabRunException::class)
//    fun selectElementType(
//        elements: LinkedList<WebElement>,
//        it: BrowserReptileTask.Step,
//        operating: DriverOperating,
//        elementIndex: Int
//    ): Int {
//        var element: WebElement? = null
//        //获取父元素
//        if (it.useCurrentEle && elements.size > 0 && elementIndex >= 0) {
//            element = elements[elementIndex]
//        }
//        elements.clear()
//        //执行查找
//        if (StrUtil.isNotBlank(it.xpath)) {
//            elements.add(operating.getElementByXpath(it.xpath!!, element))
//            return 0
//        } else if (StrUtil.isNotBlank(it.id)) {
//            elements.add(operating.getElementById(it.id!!, element))
//            return 0
//        } else if (StrUtil.isNotBlank(it.className)) {
//            if (it.index == null) {
//                elements.addAll(operating.getElementByClass(it.className!!, element))
//                return -1
//            } else if (it.index!! >= 0) {
//                elements.add(operating.getElementByClass(it.className!!, element)[it.index!!])
//                return 0
//            }
//        } else if (StrUtil.isNotBlank(it.name)) {
//            if (it.index == null) {
//                elements.addAll(operating.getElementByName(it.name!!, element))
//                return -1
//            } else if (it.index!! >= 0) {
//                elements.add(operating.getElementByName(it.name!!, element)[it.index!!])
//                return 0
//            }
//        } else if (StrUtil.isNotBlank(it.tag)) {
//            if (it.index == null) {
//                elements.addAll(operating.getElementByTag(it.tag!!, element))
//                return -1
//            } else if (it.index!! >= 0) {
//                elements.add(operating.getElementByTag(it.tag!!, element)[it.index!!])
//                return 0
//            }
//        }
//        throw LabRunException("执行查找元素，未指定类型查找！")
//    }
//
//    @Throws(LabRunException::class)
//    fun useSelectElement(
//        elements: LinkedList<WebElement>,
//        it: BrowserReptileTask.Step,
//        operating: DriverOperating,
//        elementIndex: Int
//    ): WebElement {
//        var element: WebElement? = null
//        //获取父元素
//        if (it.useCurrentEle && elements.size > 0 && elementIndex >= 0) {
//            element = elements[elementIndex]
//        }
//        //执行查找
//        if (StrUtil.isNotBlank(it.xpath)) {
//            return operating.getElementByXpath(it.xpath!!, element)
//        } else if (StrUtil.isNotBlank(it.id)) {
//            return operating.getElementById(it.id!!, element)
//        } else if (StrUtil.isNotBlank(it.className)) {
//            if (it.index == null) {
//                return operating.getElementByClass(it.className!!, element)[0]
//            } else if (it.index!! >= 0) {
//                return operating.getElementByClass(it.className!!, element)[it.index!!]
//            }
//        } else if (StrUtil.isNotBlank(it.name)) {
//            if (it.index == null) {
//                return operating.getElementByName(it.name!!, element)[0]
//            } else if (it.index!! >= 0) {
//                return operating.getElementByName(it.name!!, element)[it.index!!]
//            }
//        } else if (StrUtil.isNotBlank(it.tag)) {
//            if (it.index == null) {
//                return operating.getElementByTag(it.tag!!, element)[0]
//            } else if (it.index!! >= 0) {
//                return operating.getElementByTag(it.tag!!, element)[it.index!!]
//            }
//        } else if (element != null) {
//            return element
//        }
//        throw LabRunException("执行查找元素，未指定类型查找！")
//    }

}